﻿using System;
using System.Collections.Generic;
using CollegeSim.Domain.DTO;
using CollegeSim.Domain.Interfaces.Repositories;
using CollegeSim.Domain.Services;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace CollegeSim.Domain.Test.Services
{
    // Author: Ryan Redburn
    // Project: CollegeSim
    // Date: 5/17/2014

    [TestClass]
    public class InstructorServiceTest
    {
        #region [ GetAll() ]

        [TestMethod]
        public void InstructorServiceGetAll_InvalidDataReceived_InvalidOperationExecption()
        {
            // Arrange
            var assert = false;
            List<InstructorDTO> instructors = null;
            var instructorReturn = new List<InstructorDTO> { new InstructorDTO { FirstName = "", LastName = "" } } as IEnumerable<InstructorDTO>;
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindAll()).Returns(instructorReturn);

            try
            {
                // Act
                instructors = instructorService.GetAll();
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
                Assert.IsNull(instructors);
            }
        }

        [TestMethod]
        public void InstructorServiceGetAll_ValidCall_ExpectedReturn()
        {
            // Arrange
            var assert = true;
            var instructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            List<InstructorDTO> instructors = null;
            var instructorReturn = new List<InstructorDTO> { instructor } as IEnumerable<InstructorDTO>;
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindAll()).Returns(instructorReturn);

            try
            {
                // Act
                instructors = instructorService.GetAll();
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
                Assert.IsNotNull(instructors);
            }
        }

        #endregion

        #region [ GetByID() ]

        [TestMethod]
        public void InstructorServiceGetByID_IDBelowRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var assert = false;
            InstructorDTO instructor = null;
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            try
            {
                // Act
                instructor = instructorService.GetByID(-1);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
                Assert.IsNull(instructor);
            }
        }

        [TestMethod]
        public void InstructorServiceGetByID_InvalidDataReceived_InvalidOperationException()
        {
            // Arrange
            var assert = false;
            InstructorDTO instructor = null;
            var invalidInstructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "",
                LastName = "",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindByID(1)).Returns(invalidInstructor);

            try
            {
                // Act
                instructor = instructorService.GetByID(1);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
                Assert.IsNull(instructor);
            }
        }

        [TestMethod]
        public void InstructorServiceGetByID_ValidCall_ExpectedReturn()
        {
            // Arrange
            var assert = true;
            InstructorDTO instructor = null;
            var instructorReturn = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindByID(1)).Returns(instructorReturn);

            try
            {
                // Act
                instructor = instructorService.GetByID(1);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
                Assert.IsNotNull(instructor);
            }
        }

        #endregion

        #region [ Commit() ]

        [TestMethod]
        public void InstructorServiceCommit_ValidCall_ExpectedReturn()
        {
            // Arrange
            var assert = true;
            var instructor = new InstructorDTO
            {
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();

            try
            {
                // Act
                instructorService.Commit(instructor);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ Update() ]

        [TestMethod]
        public void InstructorServiceUpdate_NonExistentID_InvalidOperationException()
        {
            // Arrange
            var assert = false;
            InstructorDTO instructorReturn = null;
            var instructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindByID(1)).Returns(instructorReturn);

            try
            {
                // Act
                instructorService.Update(instructor.InstructorID, instructor);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void InstructorServiceUpdate_ValidCall_ExpectedReturn()
        {
            // Arrange
            var assert = true;
            var instructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindByID(1)).Returns(instructor);

            try
            {
                // Act
                instructorService.Update(instructor.InstructorID, instructor);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ Delete() ]

        [TestMethod]
        public void InstructorServiceDelete_NonExistentID_InvalidOperationException()
        {
            // Arrange
            var assert = false;
            var instructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            try
            {
                // Act
                instructorService.Delete(instructor);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void InstructorServiceDelete_ValidCall_ExpectedReturn()
        {
            // Arrange
            var assert = true;
            var instructor = new InstructorDTO
            {
                InstructorID = 1,
                FirstName = "Ryan",
                LastName = "Redburn",
                PhoneNumber = "123-456-7890",
                Email = "rredburn@domain.com",
                OfficeNumber = "PS204"
            };
            var instructorRepo = new Mock<IInstructorRepository>();
            var instructorService = new InstructorService(instructorRepo.Object);

            DomainMapConfig.Initialize();
            instructorRepo.Setup(ir => ir.FindByID(1)).Returns(instructor);

            try
            {
                // Act
                instructorService.Delete(instructor);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion
    }
}
